/**
 * Vector2 对象池 - 减少临时对象创建
 */
class Vector2Pool {
    private static pool: Vector2[] = [];
    private static maxPoolSize = 200;
    private static hits = 0;
    private static misses = 0;
    
    static acquire(x: number = 0, y: number = 0): Vector2 {
        if (this.pool.length > 0) {
            this.hits++;
            const v = this.pool.pop()!;
            v.x = x;
            v.y = y;
            return v;
        }
        this.misses++;
        return new Vector2(x, y);
    }
    
    static release(v: Vector2): void {
        if (this.pool.length < this.maxPoolSize) {
            v.x = 0;
            v.y = 0;
            this.pool.push(v);
        }
    }
    
    static clear(): void {
        this.pool.length = 0;
        this.hits = 0;
        this.misses = 0;
    }
    
    static getStats() {
        return {
            poolSize: this.pool.length,
            hits: this.hits,
            misses: this.misses,
            hitRate: this.hits / Math.max(1, this.hits + this.misses)
        };
    }
}

/**
 * 2D 向量类
 * 用于 RVO 算法的向量运算
 * 
 * @优化说明
 * - 支持对象池复用（通过 Vector2Pool）
 * - 添加内联计算方法减少临时对象
 */
export class Vector2 {
    x: number = 0;
    y: number = 0;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    /**
     * 向量加法（创建新对象）
     */
    plus(vector: Vector2): Vector2 {
        return new Vector2(this.x + vector.x, this.y + vector.y);
    }
    
    /**
     * 向量加法（原地修改）
     * @优化: 避免创建临时对象
     */
    plusInPlace(vector: Vector2): this {
        this.x += vector.x;
        this.y += vector.y;
        return this;
    }

    /**
     * 向量减法（创建新对象）
     */
    minus(vector: Vector2): Vector2 {
        return new Vector2(this.x - vector.x, this.y - vector.y);
    }
    
    /**
     * 向量减法（原地修改）
     * @优化: 避免创建临时对象
     */
    minusInPlace(vector: Vector2): this {
        this.x -= vector.x;
        this.y -= vector.y;
        return this;
    }

    /**
     * 向量点积
     */
    multiply(vector: Vector2): number {
        return this.x * vector.x + this.y * vector.y;
    }
    
    /**
     * 向量点积（静态版本，更快）
     * @优化: 内联计算
     */
    static dot(v1: Vector2, v2: Vector2): number {
        return v1.x * v2.x + v1.y * v2.y;
    }

    /**
     * 向量缩放（创建新对象）
     */
    scale(k: number): Vector2 {
        return new Vector2(this.x * k, this.y * k);
    }
    
    /**
     * 向量缩放（原地修改）
     * @优化: 避免创建临时对象
     */
    scaleInPlace(k: number): this {
        this.x *= k;
        this.y *= k;
        return this;
    }

    /**
     * 复制向量值（支持 Cocos Vec2）
     */
    copy(v: Vector2 | { x: number; y: number }): this {
        this.x = v.x;
        this.y = v.y;
        return this;
    }

    /**
     * 克隆向量
     */
    clone(): Vector2 {
        return new Vector2(this.x, this.y);
    }

    /**
     * 向量减法（修改 out）
     */
    substract(out: Vector2, other: Vector2): Vector2 {
        out.x -= other.x;
        out.y -= other.y;
        return out;
    }

    /**
     * 向量长度的平方
     */
    lengthSqr(): number {
        return this.x ** 2 + this.y ** 2;
    }

    /**
     * 向量长度
     */
    length(): number {
        return Math.sqrt(this.lengthSqr());
    }

    /**
     * 归一化（返回新向量）
     */
    normalize(): Vector2 {
        const len = this.length();
        if (len === 0) return new Vector2(0, 0);
        return this.scale(1 / len);
    }
    
    /**
     * 归一化（原地修改）
     * @优化: 避免创建临时对象
     */
    normalizeInPlace(): this {
        const len = this.length();
        if (len > 0) {
            const invLen = 1 / len;
            this.x *= invLen;
            this.y *= invLen;
        }
        return this;
    }

    /**
     * 设置向量值
     */
    set(x: number, y: number): this {
        this.x = x;
        this.y = y;
        return this;
    }
    
    /**
     * 重置向量为零
     * @优化: 快速重置
     */
    reset(): this {
        this.x = 0;
        this.y = 0;
        return this;
    }

    /**
     * 转换为字符串
     */
    toString(): string {
        return `Vector2(${this.x.toFixed(2)}, ${this.y.toFixed(2)})`;
    }
    
    /**
     * 获取对象池统计
     */
    static getPoolStats() {
        return Vector2Pool.getStats();
    }
    
    /**
     * 清理对象池
     */
    static clearPool() {
        Vector2Pool.clear();
    }
}

/**
 * 障碍物类
 * 用于静态障碍物避让
 */
export class Obstacle {
    next: Obstacle | null = null;
    previous: Obstacle | null = null;
    direction: Vector2 = new Vector2(0, 0);
    point: Vector2 = new Vector2(0, 0);
    id: number = 0;
    convex: boolean = false;
}

/**
 * 线段类
 * 用于 ORCA 算法的线性约束
 */
export class Line {
    point: Vector2 = new Vector2(0, 0);
    direction: Vector2 = new Vector2(0, 0);
}

/**
 * 键值对类
 * 用于邻居搜索的结果存储
 */
export class KeyValuePair<K, V> {
    key: K;
    value: V;
    
    constructor(key: K, value: V) {
        this.key = key;
        this.value = value;
    }
}

/**
 * RVO 数学工具类
 * 提供向量运算和几何计算
 * 
 * @优化说明
 * - 内联计算减少临时对象创建
 * - 缓存常用计算结果
 */
export class RVOMath {

    /** 浮点数精度阈值 */
    static readonly RVO_EPSILON = 0.00001;

    /**
     * 向量长度的平方
     */
    static absSq(v: Vector2): number {
        return v.multiply(v);
    }
    
    /**
     * 向量长度的平方（内联版本）
     * @优化: 内联计算，避免方法调用
     */
    static absSqInline(v: Vector2): number {
        return v.x * v.x + v.y * v.y;
    }

    /**
     * 向量归一化
     */
    static normalize(v: Vector2): Vector2 {
        const len = RVOMath.abs(v);
        if (len === 0) return new Vector2(0, 0);
        return v.scale(1 / len);
    }
    
    /**
     * 向量归一化（内联版本，输出到指定向量）
     * @优化: 避免创建临时对象
     */
    static normalizeOut(v: Vector2, out: Vector2): Vector2 {
        const lenSq = v.x * v.x + v.y * v.y;
        if (lenSq > 0) {
            const invLen = 1 / Math.sqrt(lenSq);
            out.x = v.x * invLen;
            out.y = v.y * invLen;
        } else {
            out.x = 0;
            out.y = 0;
        }
        return out;
    }

    /**
     * 点到线段的距离平方
     */
    static distSqPointLineSegment(
        vector1: Vector2,
        vector2: Vector2,
        vector3: Vector2
    ): number {
        const aux1 = vector3.minus(vector1);
        const aux2 = vector2.minus(vector1);

        const r = aux1.multiply(aux2) / RVOMath.absSq(aux2);

        if (r < 0) {
            return RVOMath.absSq(aux1);
        } else if (r > 1) {
            return RVOMath.absSq(vector3.minus(vector2));
        } else {
            return RVOMath.absSq(vector3.minus(vector1.plus(aux2.scale(r))));
        }
    }
    
    /**
     * 点到线段的距离平方（优化版，内联计算）
     * @优化: 完全内联，零临时对象
     */
    static distSqPointLineSegmentOptimized(
        v1: Vector2,
        v2: Vector2,
        v3: Vector2
    ): number {
        // aux1 = v3 - v1
        const aux1X = v3.x - v1.x;
        const aux1Y = v3.y - v1.y;
        
        // aux2 = v2 - v1
        const aux2X = v2.x - v1.x;
        const aux2Y = v2.y - v1.y;
        
        // r = dot(aux1, aux2) / dot(aux2, aux2)
        const aux2LenSq = aux2X * aux2X + aux2Y * aux2Y;
        const r = (aux1X * aux2X + aux1Y * aux2Y) / aux2LenSq;
        
        if (r < 0) {
            // 返回 |aux1|²
            return aux1X * aux1X + aux1Y * aux1Y;
        } else if (r > 1) {
            // 返回 |v3 - v2|²
            const dx = v3.x - v2.x;
            const dy = v3.y - v2.y;
            return dx * dx + dy * dy;
        } else {
            // 返回 |v3 - (v1 + aux2 * r)|²
            const projX = v1.x + aux2X * r;
            const projY = v1.y + aux2Y * r;
            const dx = v3.x - projX;
            const dy = v3.y - projY;
            return dx * dx + dy * dy;
        }
    }

    /**
     * 数值平方
     */
    static sqr(p: number): number {
        return p * p;
    }

    /**
     * 向量叉积（2D 行列式）
     */
    static det(v1: Vector2, v2: Vector2): number {
        return v1.x * v2.y - v1.y * v2.x;
    }

    /**
     * 向量长度
     */
    static abs(v: Vector2): number {
        return Math.sqrt(RVOMath.absSq(v));
    }

    /**
     * 判断点 c 是否在向量 ab 的左侧
     */
    static leftOf(a: Vector2, b: Vector2, c: Vector2): number {
        return RVOMath.det(a.minus(c), b.minus(a));
    }
}
